use std::collections::HashMap;

use egui::Color32;
use egui_snarl::ui::{self, SnarlViewer};
use egui_snarl::{InPinId, NodeId, OutPin, OutPinId, Snarl};

use crate::data::NodeData;

use super::node::{CopyData, CopyNodeData, Node, NodeTrait};
use super::value::Value;

#[derive(Clone)]
struct NodeMenuData {
    pub name: String,
    pub sub_menus: Vec<NodeMenuData>,
    pub nodes: Vec<NodeData>,
}

pub struct Viewer {
    //跳过
    pub ui_id: Option<egui::Id>,
    pub current_tree:Option<super::node_tree::SnarlTree>,
    dirty: bool,
    pub graph_data: Option<super::GraphData>,
    pub custom_datas: HashMap<String, Value>,
    pub constants: HashMap<String, Value>,
    pub include_graphs: HashMap<String, super::Graph>,
    node_menu_datas: Option<NodeMenuData>
}

impl Viewer {
    pub fn new() -> Self {
        Self {
            ui_id: None,
            current_tree: None,
            dirty: false,
            graph_data: None,
            custom_datas: HashMap::new(),
            constants: HashMap::new(),
            include_graphs: HashMap::new(),
            node_menu_datas: None,
        }
    }

    pub fn clear_dirty(&mut self) {
        self.dirty = false;
    }
}

impl Default for Viewer {
    fn default() -> Self {
        Self::new()
    }
}

fn add_menu_data(menu_data:&mut NodeMenuData, node:&NodeData, path_index:usize) {
    match node.menu {
        Some(ref menu) => {
            let menu_paths = menu.split('/').filter(|x| !x.is_empty()).collect::<Vec<_>>();
            if path_index < menu_paths.len() {
                let mut sub_menu = NodeMenuData {
                    name: menu_paths[path_index].to_string(),
                    sub_menus: Vec::new(),
                    nodes: Vec::new(),
                };
                add_menu_data(&mut sub_menu, node, path_index + 1);
                let mut find = false;
                for sub in menu_data.sub_menus.iter_mut() {
                    if sub.name == sub_menu.name {
                        find = true;
                        add_menu_data(sub, node, path_index + 1);
                        break;
                    }
                }
                if !find {
                    menu_data.sub_menus.push(sub_menu);
                }
            } else {
                menu_data.nodes.push(node.clone());
            }
        }
        None => {
            menu_data.nodes.push(node.clone());
        }
    }
}

fn draw_node_menu_data(menu_data:&NodeMenuData, ui:&mut egui::Ui, snarl:&mut Snarl<Node>, pos:egui::Pos2) -> Option<NodeId> {
    let mut result = None;
    for sub_menu in menu_data.sub_menus.iter() {
        ui.menu_button(sub_menu.name.clone(), |ui|{
            let sub_result = draw_node_menu_data(sub_menu, ui, snarl, pos);
            if sub_result.is_some() {
                result = sub_result;
            }
        });
    }

    for node in menu_data.nodes.iter() {
        if ui.button(&node.name).clicked() {
            result = Some(snarl.insert_node(pos, Node::from(node.clone())));
        }
    }

    result
}

impl Viewer {
    fn build_nodes_menu_data(&mut self){
        let Some(ref graph_data) = self.graph_data else {
            self.node_menu_datas = None;
            return;
        };
        let mut root = NodeMenuData {
            name: "root".to_string(),
            sub_menus: Vec::new(),
            nodes: Vec::new(),
        };

        for node in graph_data.nodes.iter() {
            add_menu_data(&mut root, node, 0);
        }

        self.node_menu_datas = Some(root);
    }
}

impl Viewer {
    pub fn is_dirty(&self) ->bool {
        self.dirty
    }

    pub fn set_graph_data(&mut self, graph_data: super::GraphData) {
        self.graph_data = Some(graph_data);
        self.build_nodes_menu_data();
    }

    fn copy_nodes(&self, snarl:&Snarl<Node>, ui:&mut egui::Ui, pos:Option<egui::Pos2>, default_node:Option<egui_snarl::NodeId>) {
        let Some(ui_id) = self.ui_id else {return;};
        let mut selected_nodes = Snarl::<Node>::get_selected_nodes_at("snarl_main", ui_id, ui.ctx());
        if selected_nodes.is_empty() {
            if let Some(default_node_id) = default_node {
                selected_nodes.push(default_node_id);
            } else {
                return;
            }
        }

        let pos = if let Some(new_pos) = pos {new_pos} else {
            if let Some(first_node) = selected_nodes.first() {
                if let Some(node_info) = snarl.get_node_info(first_node.to_owned()) {
                    node_info.pos
                } else {
                    egui::Pos2::new(0.0, 0.0)
                }
            } else {
                egui::Pos2::new(0.0, 0.0)
            }
        };
        let mut copy_data = CopyData::new();
        let mut pushed_nodes = Vec::new();
        for node in selected_nodes.iter() {
            let cloned_info = snarl.get_node_info(*node).cloned();
            let Some(node_info) = cloned_info else {continue;};
            if node_info.value.can_copy() == false {
                continue;
            }
            copy_data.nodes.push(CopyNodeData {
                node: node_info.value.clone(),
                position: pos - node_info.pos,
            });
            pushed_nodes.push(*node);
        }

        for (out_pin, in_pin) in snarl.wires() {
            let Some(out_index) = pushed_nodes.iter().position(|&x| x == out_pin.node) else {continue;};
            let Some(in_index) = pushed_nodes.iter().position(|&x| x == in_pin.node) else {continue;};
            copy_data.wires.push(((out_index, out_pin.output), (in_index, in_pin.input)));
        }

        serde_json::to_string(&copy_data).ok().map(|data| {
            ui.ctx().copy_text(data);
        });
    }
}

impl SnarlViewer<Node> for Viewer {
    fn title(&mut self, node: &Node) -> String {
        node.name().to_string()
    }

    fn show_header(
            &mut self,
            node: egui_snarl::NodeId,
            _inputs: &[egui_snarl::InPin],
            _outputs: &[egui_snarl::OutPin],
            ui: &mut egui::Ui,
            _scale: f32,
            snarl: &mut Snarl<Node>,
        ) {

        if let Some(current_node) = snarl.get_node(node) {
            match current_node {
                Node::BlackboardInRef(node) => {
                    if let Some(ref_out) = snarl.get_node(node.ref_node).clone() {
                        let out_name = ref_out.name();
                        ui.label(&format!("引用:{}", out_name));
                    } else {
                        //红色文字提示引用的节点不存在
                        ui.colored_label(Color32::RED, "引用的节点不存在");
                    }
                }
                Node::Constant(node) => {
                    if self.constants.contains_key(&node.name) {
                        ui.label(&format!("常量:{}", node.name));
                    } else {
                        //红色文字提示常量不存在
                        ui.colored_label(Color32::RED, "常量不存在");
                    }
                }
                Node::CustomData(node) => {
                    if self.custom_datas.contains_key(&node.name) {
                        ui.label(&format!("自定义数据:{}", node.name));
                    } else {
                        //红色文字提示自定义数据不存在
                        ui.colored_label(Color32::RED, "自定义数据不存在");
                    }
                }
                Node::ModuleDef(_) => {
                    //可编辑的模块名称
                    let Some(Node::ModuleDef(ref_node)) = snarl.get_node_mut(node) else {return;};
                    let edit_text = egui::TextEdit::singleline(&mut ref_node.name).desired_width(100.0);
                    let response = ui.add(edit_text);
                    if response.changed() {
                        self.dirty = true;
                    }
                    if let Some(description) = ref_node.description() {
                        response.on_hover_text(description);
                    }
                    ui.add_space(0.0);
                }
                Node::ModuleRef(node) => {
                    if let Some(ref_node) = snarl.get_node(node.ref_node_id) {
                        let out_name = ref_node.name();
                        ui.label(&format!("模块引用:{}", out_name));
                    } else {
                        //红色文字提示引用的节点不存在
                        ui.colored_label(Color32::RED, "引用的节点不存在");
                    }
                }
                Node::IncludeConstant(node) => {
                    if let Some(graph) = self.include_graphs.get(&node.file) {
                        if graph.constants.contains_key(&node.name) {
                            ui.label(&format!("引用常量:{}", node.name)).on_hover_text(node.description().unwrap_or_default());
                        } else {
                            //红色文字提示常量不存在
                            ui.colored_label(Color32::RED, "常量不存在");
                        }
                    } else {
                        //红色文字提示引用的图不存在
                        ui.colored_label(Color32::RED, "引用的文件不存在");
                    }
                }
                Node::IncludeCustomData(node) => {
                    if let Some(graph) = self.include_graphs.get(&node.file) {
                        if graph.custom_datas.contains_key(&node.name) {
                            ui.label(&format!("引用自定义数据:{}", node.name)).on_hover_text(node.description().unwrap_or_default());
                        } else {
                            //红色文字提示自定义数据不存在
                            ui.colored_label(Color32::RED, "自定义数据不存在");
                        }
                    } else {
                        //红色文字提示引用的图不存在
                        ui.colored_label(Color32::RED, "引用的文件不存在");
                    }
                }
                Node::IncludeModuleRef(node) => {
                    if let Some(graph) = self.include_graphs.get(&node.file) {
                        if let Some(ref_node) = graph.snarl.nodes().find_map(|find_node|{
                            if let Node::ModuleDef(module_def_node) = find_node{
                                if module_def_node.name() == node.ref_node_name {
                                    Some(find_node)
                                } else {
                                    None
                                }
                            } else {
                                None
                            }
                        }) {
                            let out_name = ref_node.name();
                            ui.label(&format!("引用模块:{}", out_name)).on_hover_text(node.description().unwrap_or_default());
                        } else {
                            //红色文字提示引用的节点不存在
                            ui.colored_label(Color32::RED, "引用的节点不存在");
                        }
                    } else {
                        //红色文字提示引用的图不存在
                        ui.colored_label(Color32::RED, "引用的文件不存在");
                    }
                }
                _ => {
                    if snarl[node].draw_name(ui) {
                        self.dirty = true;
                    }
                }
            }
        }

        if let Some(Node::Normal(_)) = snarl.get_node(node) {
            if let Some(current_tree) = &self.current_tree {
                if let Some(node_info) = current_tree.nodes.get(&node) {
                    if let Some(parent) = node_info.parent {
                        let parent_info = current_tree.nodes.get(&parent);
                        if let Some(parent_info) = parent_info {
                            let self_index = parent_info.children.iter().position(|&x| x == node).unwrap_or(0) + 1;
                            ui.label(&format!("({}/{})", self_index, parent_info.children.len()));
                        }
                    }
                }
            } 
        }
    }

    fn outputs(&mut self, node: &Node) -> usize {
        node.outputs().len()
    }

    fn inputs(&mut self, node: &Node) -> usize {
        node.inputs().len()
    }

    fn show_input(&mut self, pin: &egui_snarl::InPin, ui: &mut egui::Ui, _scale: f32, snarl: &mut egui_snarl::Snarl<Node>)
        -> egui_snarl::ui::PinInfo {
        let Some(node) = snarl.get_node_mut(pin.id.node) else {return egui_snarl::ui::PinInfo::default();};
        let Some(input_data) = node.get_input_info_mut(pin.id.input) else {return egui_snarl::ui::PinInfo::default();};
            let response = ui.label(&input_data.name);
            if let Some(description) = &input_data.description {
                response.on_hover_text(description);
            }

        //只有未连线的时候才显示输入区域
        if pin.remotes.is_empty() {
            match &mut input_data.value {
                super::value::Value::I32(ref mut value) => {
                    let drag_value = egui::DragValue::new(value);
                    if ui.add(drag_value).changed() {
                        self.dirty = true;
                    }
                },
                super::value::Value::I64(value) => {
                    let drag_value = egui::DragValue::new(value);
                    if ui.add(drag_value).changed() {
                        self.dirty = true;
                    }
                },
                super::value::Value::F32(value) => {
                    let drag_value = egui::DragValue::new(value);
                    if ui.add(drag_value).changed() {
                        self.dirty = true;
                    }
                },
                super::value::Value::F64(value) => {
                    let drag_value = egui::DragValue::new(value);
                    if ui.add(drag_value).changed() {
                        self.dirty = true;
                    }
                },
                super::value::Value::Bool(value) => {
                    let checkbox = egui::Checkbox::new(value, "");
                    if ui.add(checkbox).changed() {
                        self.dirty = true;
                    }
                },
                super::value::Value::String(value) => {
                    let text_edit = egui::TextEdit::singleline(value).desired_width(100.0);
                    if ui.add(text_edit).changed() {
                        self.dirty = true;
                    }
                    ui.add_space(0.0);
                },
                _ => {}
            }
        }

        let color = input_data.value.value_color();
        return egui_snarl::ui::PinInfo::circle().with_fill(egui::Color32::from_rgba_premultiplied(color[0], color[1], color[2], color[3]));
    }

    fn show_output(
        &mut self,
        pin: &egui_snarl::OutPin,
        ui: &mut egui::Ui,
        _scale: f32,
        snarl: &mut egui_snarl::Snarl<Node>,
    ) -> egui_snarl::ui::PinInfo {
        let Some(node) = snarl.get_node_mut(pin.id.node) else {return egui_snarl::ui::PinInfo::default();};
        let Some(output_data) = node.get_output_info(pin.id.output) else {return egui_snarl::ui::PinInfo::default();};
        let response = ui.label(&output_data.name);
        if let Some(description) = &output_data.description {
            response.on_hover_text(description);
        }

        let color = output_data.value.value_color();
        return egui_snarl::ui::PinInfo::circle().with_fill(egui::Color32::from_rgba_premultiplied(color[0], color[1], color[2], color[3]));
    }

    fn connect(&mut self, from: &egui_snarl::OutPin, to: &egui_snarl::InPin, snarl: &mut Snarl<Node>) {
        let Some(from_node) = snarl.get_node(from.id.node) else {return;};
        let Some(from_output) = from_node.get_output_info(from.id.output) else {return;};
        let Some(to_node) = snarl.get_node(to.id.node) else {return;};
        let Some(to_input) = to_node.get_input_info(to.id.input) else {return;};
        if from_output.value.is_same_type(&to_input.value) {
            match from_output.value {
                super::value::Value::Node => {
                    if let Some(children_count) = from_node.children_count() {
                        if children_count <=  from.remotes.len() {
                            return;
                        }
                    }
                }
                _=>{}
            }
            snarl.drop_inputs(to.id);
            snarl.connect(from.id, to.id);
            self.dirty = true;
        }
    }

    fn drop_inputs(&mut self, pin: &egui_snarl::InPin, snarl: &mut Snarl<Node>) {
        snarl.drop_inputs(pin.id);
        self.dirty = true;
    }

    fn drop_outputs(&mut self, pin: &egui_snarl::OutPin, snarl: &mut Snarl<Node>) {
        snarl.drop_outputs(pin.id);
        self.dirty = true;
    }

    fn disconnect(&mut self, from: &OutPin, to: &egui_snarl::InPin, snarl: &mut Snarl<Node>) {
        snarl.disconnect(from.id, to.id);
        self.dirty = true;
    }

    fn has_graph_menu(&mut self, _pos: egui::Pos2, _snarl: &mut Snarl<Node>) -> bool {
        true
    }

    fn has_dropped_wire_menu(&mut self, _src_pins: ui::AnyPins, _snarl: &mut Snarl<Node>) -> bool {
        true
    }

    fn has_node_menu(&mut self, _node: &Node) -> bool {
        true
    }

    fn show_graph_menu(&mut self, pos: egui::Pos2, ui: &mut egui::Ui, _scale: f32, snarl: &mut Snarl<Node>) {
        if let Some(ui_id) = self.ui_id {
            let selected_nodes = Snarl::<Node>::get_selected_nodes_at("snarl_main", ui_id, ui.ctx());
            if selected_nodes.len() > 0 {
                if ui.button("删除").clicked() {
                    for node_id in selected_nodes {
                        if let Some(node) = snarl.get_node(node_id) {
                            if !node.can_delete() {
                                continue;
                            }
                        }
                        snarl.remove_node(node_id);
                    }
                    ui.close_menu();
                }

                if ui.button("复制").clicked() {
                    self.copy_nodes(snarl, ui, Some(pos), None);
                    ui.close_menu();
                }
            }
        }

        if let Some(ref menu_datas) = self.node_menu_datas {
            ui.menu_button("新建", |ui|{
                if let Some(_) = draw_node_menu_data(menu_datas, ui, snarl, pos) {
                    self.dirty = true;
                    ui.close_menu();
                }
            });
        }

        let module_defs = snarl.nodes_ids_data().filter_map(|(node_id, node_info)|{
            let node = &node_info.value;
            match node {
                Node::ModuleDef(module_def_node) => {
                    Some((node_id, module_def_node.name().to_owned()))
                }
                _ => None
            }
        }).collect::<Vec<_>>();
        if module_defs.len() > 0 {
            ui.menu_button("模块引用", |ui|{
                for (node_id, name) in module_defs.iter() {
                    if ui.button(name).clicked() {
                        let ref_node = Node::new_module_ref(node_id.to_owned());
                        snarl.insert_node(pos, ref_node);
                        self.dirty = true;
                        ui.close_menu();
                    }
                }
            });
        }

        let mut all_include_refs:HashMap<String, Vec<_>> = HashMap::new();
        for (file, graph) in self.include_graphs.iter() {
            let snarl = &graph.snarl;
            let all_refnodes = snarl.nodes_ids_data().filter_map(|(node_id, node_info)|{
                let node = &node_info.value;
                match node {
                    Node::ModuleDef(_) => {
                        Some((node_id, node.name().to_owned()))
                    }
                    _ => None
                }
            }).collect::<Vec<_>>();
            if all_refnodes.len() > 0 {
                all_include_refs.insert(file.to_owned(), all_refnodes);
            } 
        }

        if all_include_refs.len() > 0 {
            ui.menu_button("外部文件模块引用", |ui|{
                for (file, datas) in all_include_refs.iter() {
                    ui.menu_button(file, |ui|{
                        for (_, name) in datas.iter() {
                            if ui.button(name).clicked() {
                                let ref_node = Node::new_include_module_ref(file.to_owned(), name.to_owned());
                                snarl.insert_node(pos, ref_node);
                                self.dirty = true;
                                ui.close_menu();
                            }
                        }
                    });
                }
            });
        }

        if ui.button("新模块").clicked() {
            let ref_node = Node::new_module_def("新模块".to_owned());
            snarl.insert_node(pos, ref_node);
            self.dirty = true;
            ui.close_menu();
        }

        //检查引用节点
        let all_refnodes = snarl.nodes_ids_data().filter_map(|(node_id, node_info)|{
            let node = &node_info.value;
            match node {
                Node::BlackboardOutRef(out_node) => {
                    Some((node_id, out_node.value.clone(), node.name().to_owned()))
                }
                _ => None
            }
        }).collect::<Vec<_>>();

        if all_refnodes.len() > 0 {
            ui.menu_button("引用", |ui|{
                for (node_id, value, name) in all_refnodes.iter() {
                    if ui.button(name).clicked() {
                        let ref_node = Node::new_blackboard_in_ref(node_id.to_owned(), value.clone());
                        snarl.insert_node(pos, ref_node);
                        self.dirty = true;
                        ui.close_menu();
                    }
                }
            });
        }

        if self.constants.len() > 0 {
            ui.menu_button("常量引用", |ui|{
                for (name, value) in self.constants.iter() {
                    if ui.button(name).clicked() {
                        let ref_node = Node::new_constant(name.to_owned(), value.clone());
                        snarl.insert_node(pos, ref_node);
                        self.dirty = true;
                        ui.close_menu();
                    }
                }
            });
        }

        if self.custom_datas.len() > 0 {
            ui.menu_button("自定义数据引用", |ui|{
                for (name, value) in self.custom_datas.iter() {
                    if ui.button(name).clicked() {
                        let ref_node = Node::new_custom_data(name.to_owned(), value.clone());
                        snarl.insert_node(pos, ref_node);
                        self.dirty = true;
                        ui.close_menu();
                    }
                }
            });
        }

        let mut include_custom_datas:HashMap<String, Vec<_>> = HashMap::new();
        let mut include_constants:HashMap<String, Vec<_>> = HashMap::new();
        for (file, graph) in self.include_graphs.iter() {
            for (name, value) in graph.custom_datas.iter() {
                include_custom_datas.entry(file.to_owned()).or_insert(Vec::new()).push((name.to_owned(), value.clone()));
            }
            for (name, value) in graph.constants.iter() {
                include_constants.entry(file.to_owned()).or_insert(Vec::new()).push((name.to_owned(), value.clone()));
            }
        }

        if include_custom_datas.len() > 0 {
            ui.menu_button("引用自定义数据", |ui|{
                for (file, datas) in include_custom_datas.iter() {
                    ui.menu_button(file, |ui|{
                        for (name, value) in datas.iter() {
                            if ui.button(name).clicked() {
                                let ref_node = Node::new_include_custom_data(file.to_owned(), name.to_owned(), value.clone());
                                snarl.insert_node(pos, ref_node);
                                self.dirty = true;
                                ui.close_menu();
                            }
                        }
                    });
                }
            });
        }

        if include_constants.len() > 0 {
            ui.menu_button("引用常量", |ui|{
                for (file, datas) in include_constants.iter() {
                    ui.menu_button(file, |ui|{
                        for (name, value) in datas.iter() {
                            if ui.button(name).clicked() {
                                let ref_node = Node::new_include_constant(file.to_owned(), name.to_owned(), value.clone());
                                snarl.insert_node(pos, ref_node);
                                self.dirty = true;
                                ui.close_menu();
                            }
                        }
                    });
                }
            });
        }

        //检查剪切板
        if ui.button("粘贴").clicked() {
            if let Ok(mut clipboard) = arboard::Clipboard::new() {
                if let Ok(data) = clipboard.get_text() {
                    if let Ok(copy_data) = serde_json::from_str::<CopyData>(&data) {
                        let mut node_map = Vec::new();
                        for copy_node in copy_data.nodes.iter() {
                            let node_id = snarl.insert_node(pos - copy_node.position, copy_node.node.clone());
                            node_map.push(node_id);
                        }

                        for (out, in_) in copy_data.wires.iter() {
                            let Some(out_node_id) = node_map.get(out.0) else {continue;};
                            let Some(in_node_id) = node_map.get(in_.0) else {continue;};
                            let out_pin = snarl.out_pin(OutPinId{
                                node: *out_node_id,
                                output: out.1,
                            });
                            let in_pin = snarl.in_pin(InPinId{
                                node: *in_node_id,
                                input: in_.1,
                            });
                            self.connect(&out_pin, &in_pin, snarl);
                        }

                        self.dirty = true;
                    }
                }
            }
            ui.close_menu();
            return;
        }
    }

    fn show_dropped_wire_menu(
            &mut self,
            pos: egui::Pos2,
            ui: &mut egui::Ui,
            _scale: f32,
            src_pins: ui::AnyPins,
            snarl: &mut Snarl<Node>,
        ) {
        match src_pins {
            ui::AnyPins::Out(out_pins) => {
                let Some(out_pin) = out_pins.first() else {return;};
                let Some(node) = snarl.get_node(out_pin.node) else {return;};
                let Some(output) = node.get_output_info(out_pin.output) else {return;};
                match output.value {
                    super::value::Value::Node => {
                        let out = snarl.out_pin(out_pin.clone());
                        if let Some(menu_data) = self.node_menu_datas.clone() {
                            ui.menu_button("新建", |ui|{
                                if let Some(to_node_id) = draw_node_menu_data(&menu_data, ui, snarl, pos) {
                                    let to = snarl.in_pin(InPinId{
                                        node: to_node_id,
                                        input: 0,
                                    });
                                    self.connect(&out, &to, snarl);
                                    self.dirty = true;
                                    ui.close_menu();
                                }
                            });
                        }

                        let module_defs = snarl.nodes_ids_data().filter_map(|(node_id, node_info)|{
                            let node = &node_info.value;
                            match node {
                                Node::ModuleDef(module_def_node) => {
                                    Some((node_id, module_def_node.name().to_owned()))
                                }
                                _ => None
                            }
                        }).collect::<Vec<_>>();
                        if module_defs.len() > 0 {
                            ui.menu_button("模块引用", |ui|{
                                for (node_id, name) in module_defs.iter() {
                                    if ui.button(name).clicked() {
                                        let ref_node = Node::new_module_ref(node_id.to_owned());
                                        let ref_node_id = snarl.insert_node(pos, ref_node);
                                        let to = snarl.in_pin(InPinId{
                                            node: ref_node_id,
                                            input: 0,
                                        });
                                        self.connect(&out, &to, snarl);
                                        self.dirty = true;
                                        ui.close_menu();
                                    }
                                }
                            });
                        }

                        let mut all_include_refs:HashMap<String, Vec<_>> = HashMap::new();
                        for (file, graph) in self.include_graphs.iter() {
                            let snarl = &graph.snarl;
                            let all_refnodes = snarl.nodes_ids_data().filter_map(|(node_id, node_info)|{
                                let node = &node_info.value;
                                match node {
                                    Node::ModuleDef(_) => {
                                        Some((node_id, node.name().to_owned()))
                                    }
                                    _ => None
                                }
                            }).collect::<Vec<_>>();
                            if all_refnodes.len() > 0 {
                                all_include_refs.insert(file.to_owned(), all_refnodes);
                            } 
                        }

                        if all_include_refs.len() > 0 {
                            ui.menu_button("外部文件模块引用", |ui|{
                                for (file, datas) in all_include_refs.iter() {
                                    ui.menu_button(file, |ui|{
                                        for (_, name) in datas.iter() {
                                            if ui.button(name).clicked() {
                                                let ref_node = Node::new_include_module_ref(file.to_owned(), name.to_owned());
                                                let ref_node_id = snarl.insert_node(pos, ref_node);
                                                let to = snarl.in_pin(InPinId{
                                                    node: ref_node_id,
                                                    input: 0,
                                                });
                                                self.connect(&out, &to, snarl);
                                                self.dirty = true;
                                                ui.close_menu();
                                            }
                                        }
                                    });
                                }
                            });
                        }
                    }
                    _ => {
                        if ui.button("新引用").clicked() {
                            let new_ref_node = Node::new_blackboard_out_ref(output.value.clone());
                            let node_id = snarl.insert_node(pos, new_ref_node);
                            let in_pin = snarl.in_pin(InPinId{
                                node: node_id,
                                input: 0,
                            });
                            let out = snarl.out_pin(out_pin.clone());
                            self.connect(&out, &in_pin, snarl);
                            self.dirty = true;
                            ui.close_menu();
                        }
                    }
                }
            },

            ui::AnyPins::In(in_pins) => {
                let Some(in_pin) = in_pins.first() else {return;};
                let Some(node) = snarl.get_node(in_pin.node) else {return;};
                let Some(input) = node.get_input_info(in_pin.input) else {return;};
                match input.value {
                    super::value::Value::Node => {
                        if let Some(menu_data) = self.node_menu_datas.clone() {
                            let in_pin = snarl.in_pin(in_pin.clone());
                            ui.menu_button("新建", |ui|{
                                if let Some(to_node_id) = draw_node_menu_data(&menu_data, ui, snarl, pos) {
                                    let to = snarl.out_pin(OutPinId{
                                        node: to_node_id,
                                        output: 0,
                                    });
                                    self.connect(&to, &in_pin, snarl);
                                    self.dirty = true;
                                    ui.close_menu();
                                }
                            });
                        }
                    }
                    _=> {
                        let target_value = input.value.clone();
                        let all_refnodes = snarl.nodes_ids_data().filter_map(|(node_id, node_info)|{
                            let node = &node_info.value;
                            match node {
                                Node::BlackboardOutRef(out_node) => {
                                    if out_node.value.is_same_type(&target_value) {
                                        Some((node_id, node.name().to_owned()))
                                    } else {
                                        None
                                    }
                                }
                                _ => None
                            }
                        }).collect::<Vec<_>>();
                        if all_refnodes.len() > 0 {
                            ui.menu_button("引用", |ui|{
                                let in_pin = snarl.in_pin(in_pin.clone());
                                for (node_id, name) in all_refnodes.iter() {
                                    if ui.button(name).clicked() {
                                        let ref_node = Node::new_blackboard_in_ref(node_id.to_owned(), target_value.clone());
                                        let ref_node_id = snarl.insert_node(pos, ref_node);
                                        let out = snarl.out_pin(OutPinId{
                                            node: ref_node_id,
                                            output: 0,
                                        });
                                        self.connect(&out, &in_pin, snarl);
                                        self.dirty = true;
                                        ui.close_menu();
                                    }
                                }
                            });                        
                        }

                        if self.constants.len() > 0 {
                            ui.menu_button("常量引用", |ui|{
                                let in_pin = snarl.in_pin(in_pin.clone());
                                let mut target_out:Option<OutPin> = None;
                                for (name, value) in self.constants.iter() {
                                    if value.is_same_type(&target_value) {
                                        if ui.button(name).clicked() {
                                            let ref_node = Node::new_constant(name.to_owned(), target_value.clone());
                                            let ref_node_id = snarl.insert_node(pos, ref_node);
                                            let out = snarl.out_pin(OutPinId{
                                                node: ref_node_id,
                                                output: 0,
                                            });
                                            ui.close_menu();
                                            self.dirty = true;
                                            target_out = Some(out);
                                        }
                                    }
                                }
                                if let Some(out) = target_out {
                                    self.connect(&out, &in_pin, snarl);
                                }
                            });
                        }

                        if self.custom_datas.len() > 0 {
                            ui.menu_button("自定义数据引用", |ui|{
                                let in_pin = snarl.in_pin(in_pin.clone());
                                let mut target_out:Option<OutPin> = None;
                                for (name, value) in self.custom_datas.iter() {
                                    if value.is_same_type(&target_value) {
                                        if ui.button(name).clicked() {
                                            let ref_node = Node::new_custom_data(name.to_owned(), target_value.clone());
                                            let ref_node_id = snarl.insert_node(pos, ref_node);
                                            let out = snarl.out_pin(OutPinId{
                                                node: ref_node_id,
                                                output: 0,
                                            });
                                            ui.close_menu();
                                            self.dirty = true;
                                            target_out = Some(out);
                                        }
                                    }
                                }
                                if let Some(out) = target_out {
                                    self.connect(&out, &in_pin, snarl);
                                }
                            });
                        }

                        let mut include_custom_datas:HashMap<String, Vec<_>> = HashMap::new();
                        let mut include_constants:HashMap<String, Vec<_>> = HashMap::new();
                        for (file, graph) in self.include_graphs.iter() {
                            for (name, value) in graph.custom_datas.iter() {
                                if value.is_same_type(&target_value) {
                                    include_custom_datas.entry(file.to_owned()).or_insert(Vec::new()).push((name.to_owned(), value.clone()));
                                }
                            }
                            for (name, value) in graph.constants.iter() {
                                if value.is_same_type(&target_value) {
                                    include_constants.entry(file.to_owned()).or_insert(Vec::new()).push((name.to_owned(), value.clone()));
                                }
                            }
                        }

                        if include_constants.len() > 0 {
                            ui.menu_button("外部常量引用", |ui|{
                                let in_pin = snarl.in_pin(in_pin.clone());
                                for (file, constants) in include_constants.iter() {
                                    ui.menu_button(file, |ui|{
                                        for (name, value) in constants.iter() {
                                            if ui.button(name).clicked() {
                                                let ref_node = Node::new_constant(name.to_owned(), value.clone());
                                                let ref_node_id = snarl.insert_node(pos, ref_node);
                                                let out = snarl.out_pin(OutPinId{
                                                    node: ref_node_id,
                                                    output: 0,
                                                });
                                                ui.close_menu();
                                                self.dirty = true;
                                                self.connect(&out, &in_pin, snarl);
                                            }
                                        }
                                    });
                                }
                            });
                        }

                        if include_custom_datas.len() > 0 {
                            ui.menu_button("外部自定义数据引用", |ui|{
                                let in_pin = snarl.in_pin(in_pin.clone());
                                for (file, custom_datas) in include_custom_datas.iter() {
                                    ui.menu_button(file, |ui|{
                                        for (name, value) in custom_datas.iter() {
                                            if ui.button(name).clicked() {
                                                let ref_node = Node::new_custom_data(name.to_owned(), value.clone());
                                                let ref_node_id = snarl.insert_node(pos, ref_node);
                                                let out = snarl.out_pin(OutPinId{
                                                    node: ref_node_id,
                                                    output: 0,
                                                });
                                                ui.close_menu();
                                                self.dirty = true;
                                                self.connect(&out, &in_pin, snarl);
                                            }
                                        }
                                    });
                                }
                            });
                        }
                    }
                }
            },
        }
        

    }

    fn show_node_menu(
            &mut self,
            node: egui_snarl::NodeId,
            _inputs: &[egui_snarl::InPin],
            _outputs: &[egui_snarl::OutPin],
            ui: &mut egui::Ui,
            _scale: f32,
            snarl: &mut Snarl<Node>,
        ) {
        if let Some(ui_id) = self.ui_id {
            if ui.button("删除").clicked() {
                let mut selected_nodes = Snarl::<Node>::get_selected_nodes_at("snarl_main", ui_id, ui.ctx());
                if selected_nodes.is_empty() {
                    selected_nodes.push(node);
                }
                for node_id in selected_nodes {
                    if let Some(node) = snarl.get_node(node_id) {
                        if !node.can_delete() {
                            continue;
                        }
                    }
                    snarl.remove_node(node_id);
                }
                ui.close_menu();
            }

            if ui.button("复制").clicked() {
                let Some(node_pos) = snarl.get_node_info(node).map(|info| info.pos) else {
                    ui.close_menu();
                    return;
                };
                self.copy_nodes(&snarl, ui, Some(node_pos), Some(node));
                ui.close_menu();
            }
        }
    }

}
